package Injector

import (
	"fmt"
	"github.com/shenyisyn/goft-expr/src/expr"
	"reflect"
)

var BeanmapperIml *BeanFactory

func init() {
	BeanmapperIml = NewBeanFactory()
}

type BeanFactory struct {
	beamapper mapper
	ExprMap   map[string]interface{}
}

func NewBeanFactory() *BeanFactory {
	return &BeanFactory{beamapper: make(mapper)}
}
func (this *BeanFactory) Set(vils ...interface{}) {
	if vils == nil {
		return
	}
	for _, v := range vils {
		this.beamapper.set(v)
	}
}
func (this *BeanFactory) Get(v interface{}) interface{} {
	if v == nil {
		return nil
	}
	res := this.beamapper.get(v)
	if v == nil || !res.IsValid() {
		return nil
	}
	return res.Interface()
}
func (this *BeanFactory) Config(cvgs ...interface{}) {
	for _, cvg := range cvgs {
		ty := reflect.TypeOf(cvg)
		if ty.Kind() != reflect.Ptr {
			panic("must ptr")
		}
		this.Set(ty)
		this.ExprMap = map[string]interface{}{
			ty.Elem().Name(): cvg,
		}
		va := reflect.ValueOf(cvg)
		for i := 0; i < ty.NumMethod(); i++ {
			method := va.Method(i)
			callRet := method.Call(nil)
			fmt.Println("--------------------")
			if callRet != nil && len(callRet) == 1 {
				this.Set(callRet[0].Interface())
			}
		}
	}
}
func (this *BeanFactory) Apply(bean interface{}) {
	if bean == nil {
		return
	}
	v := reflect.ValueOf(bean)
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	} else {
		return
	}
	if v.Kind() != reflect.Struct {
		return
	}
	for i := 0; i < v.NumField(); i++ {
		field := v.Type().Field(i)
		if v.Field(i).CanSet() && field.Tag.Get("inject") != "" {
			if field.Tag.Get("inject") == "-" {
				if ok := this.Get(field.Type); ok != nil {
					v.Field(i).Set(reflect.ValueOf(ok))
				}
			} else {
				//if get_v := this.Get(field.Type); get_v != nil {
				//	v.Field(i).Set(reflect.ValueOf(get_v))
				//	continue
				//}
				fmt.Println("使用表达式")
				res := expr.BeanExpr(field.Tag.Get("inject"), this.ExprMap) //ServiceConfig.OrderService()"ServiceConfig":server.NewOrderServer(),
				if res != nil && !res.IsEmpty() {
					retValue := res[0]
					if retValue != nil {
						this.Set(retValue)
						v.Field(i).Set(reflect.ValueOf(res[0]))
						this.Apply(retValue)
					}

				}
			}
		}
	}
}
